#include <graphene.h>
+struct _GskVulkanPipelineLayout
+{
+ volatile gint ref_count;
+ GdkVulkanContext *vulkan;
+
+ VkPipelineLayout pipeline_layout;
+ VkDescriptorSetLayout descriptor_set_layout;
+};
+
struct _GskVulkanPipeline
{
GObject parent_instance;
- GdkVulkanContext *vulkan;
+ GskVulkanPipelineLayout *layout;
VkPipeline pipeline;
- VkPipelineLayout pipeline_layout;
- VkDescriptorSetLayout descriptor_set_layout;
GskVulkanShader *vertex_shader;
GskVulkanShader *fragment_shader;
gsk_vulkan_pipeline_finalize (GObject *gobject)
{
GskVulkanPipeline *self = GSK_VULKAN_PIPELINE (gobject);
- VkDevice device = gdk_vulkan_context_get_device (self->vulkan);
+ VkDevice device = gdk_vulkan_context_get_device (self->layout->vulkan);
vkDestroyPipeline (device,
self->pipeline,
g_clear_pointer (&self->fragment_shader, gsk_vulkan_shader_free);
g_clear_pointer (&self->vertex_shader, gsk_vulkan_shader_free);
- vkDestroyPipelineLayout (device,
- self->pipeline_layout,
- NULL);
-
- vkDestroyDescriptorSetLayout (device,
- self->descriptor_set_layout,
- NULL);
-
- g_clear_object (&self->vulkan);
+ g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref);
G_OBJECT_CLASS (gsk_vulkan_pipeline_parent_class)->finalize (gobject);
}
}
GskVulkanPipeline *
-gsk_vulkan_pipeline_new (GdkVulkanContext *context,
- VkRenderPass render_pass)
+gsk_vulkan_pipeline_new (GskVulkanPipelineLayout *layout,
+ const char *shader_name,
+ VkRenderPass render_pass)
{
GskVulkanPipeline *self;
VkDevice device;
- g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), NULL);
+ g_return_val_if_fail (layout != NULL, NULL);
+ g_return_val_if_fail (shader_name != NULL, NULL);
g_return_val_if_fail (render_pass != VK_NULL_HANDLE, NULL);
- device = gdk_vulkan_context_get_device (context);
-
self = g_object_new (GSK_TYPE_VULKAN_PIPELINE, NULL);
- self->vulkan = g_object_ref (context);
-
- GSK_VK_CHECK (vkCreateDescriptorSetLayout, device,
- &(VkDescriptorSetLayoutCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .bindingCount = 1,
- .pBindings = (VkDescriptorSetLayoutBinding[1]) {
- {
- .binding = 0,
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .descriptorCount = 1,
- .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
- }
- }
- },
- NULL,
- &self->descriptor_set_layout);
+ self->layout = gsk_vulkan_pipeline_layout_ref (layout);
- GSK_VK_CHECK (vkCreatePipelineLayout, device,
- &(VkPipelineLayoutCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .setLayoutCount = 1,
- .pSetLayouts = &self->descriptor_set_layout,
- .pushConstantRangeCount = gst_vulkan_push_constants_get_range_count (),
- .pPushConstantRanges = gst_vulkan_push_constants_get_ranges ()
- },
- NULL,
- &self->pipeline_layout);
+ device = gdk_vulkan_context_get_device (layout->vulkan);
- self->vertex_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_VERTEX, "blit", NULL);
- self->fragment_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_FRAGMENT, "blit", NULL);
+ self->vertex_shader = gsk_vulkan_shader_new_from_resource (layout->vulkan, GSK_VULKAN_SHADER_VERTEX, shader_name, NULL);
+ self->fragment_shader = gsk_vulkan_shader_new_from_resource (layout->vulkan, GSK_VULKAN_SHADER_FRAGMENT, shader_name, NULL);
GSK_VK_CHECK (vkCreateGraphicsPipelines, device,
VK_NULL_HANDLE,
VK_DYNAMIC_STATE_SCISSOR
},
},
- .layout = self->pipeline_layout,
+ .layout = gsk_vulkan_pipeline_layout_get_pipeline_layout (self->layout),
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = VK_NULL_HANDLE,
NULL,
&self->pipeline);
-
return self;
}
return self->pipeline;
}
+/*** GskVulkanPipelineLayout ***/
+
+GskVulkanPipelineLayout *
+gsk_vulkan_pipeline_layout_new (GdkVulkanContext *context)
+{
+ GskVulkanPipelineLayout *self;
+ VkDevice device;
+
+ self = g_slice_new0 (GskVulkanPipelineLayout);
+ self->ref_count = 1;
+ self->vulkan = g_object_ref (context);
+
+ device = gdk_vulkan_context_get_device (context);
+
+ GSK_VK_CHECK (vkCreateDescriptorSetLayout, device,
+ &(VkDescriptorSetLayoutCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .bindingCount = 1,
+ .pBindings = (VkDescriptorSetLayoutBinding[1]) {
+ {
+ .binding = 0,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .descriptorCount = 1,
+ .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
+ }
+ }
+ },
+ NULL,
+ &self->descriptor_set_layout);
+
+ GSK_VK_CHECK (vkCreatePipelineLayout, device,
+ &(VkPipelineLayoutCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .setLayoutCount = 1,
+ .pSetLayouts = &self->descriptor_set_layout,
+ .pushConstantRangeCount = gst_vulkan_push_constants_get_range_count (),
+ .pPushConstantRanges = gst_vulkan_push_constants_get_ranges ()
+ },
+ NULL,
+ &self->pipeline_layout);
+
+ return self;
+}
+
+GskVulkanPipelineLayout *
+gsk_vulkan_pipeline_layout_ref (GskVulkanPipelineLayout *self)
+{
+ self->ref_count++;
+
+ return self;
+}
+
+void
+gsk_vulkan_pipeline_layout_unref (GskVulkanPipelineLayout *self)
+{
+ VkDevice device;
+
+ self->ref_count--;
+
+ if (self->ref_count > 0)
+ return;
+
+ device = gdk_vulkan_context_get_device (self->vulkan);
+
+ vkDestroyPipelineLayout (device,
+ self->pipeline_layout,
+ NULL);
+
+ vkDestroyDescriptorSetLayout (device,
+ self->descriptor_set_layout,
+ NULL);
+
+ g_slice_free (GskVulkanPipelineLayout, self);
+}
+
+
VkPipelineLayout
-gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self)
+gsk_vulkan_pipeline_layout_get_pipeline_layout (GskVulkanPipelineLayout *self)
{
return self->pipeline_layout;
}
VkDescriptorSetLayout
-gsk_vulkan_pipeline_get_descriptor_set_layout (GskVulkanPipeline *self)
+gsk_vulkan_pipeline_layout_get_descriptor_set_layout (GskVulkanPipelineLayout *self)
{
return self->descriptor_set_layout;
}
G_BEGIN_DECLS
+typedef struct _GskVulkanPipelineLayout GskVulkanPipelineLayout;
+
#define GSK_TYPE_VULKAN_PIPELINE (gsk_vulkan_pipeline_get_type ())
G_DECLARE_FINAL_TYPE (GskVulkanPipeline, gsk_vulkan_pipeline, GSK, VULKAN_PIPELINE, GObject)
#define GSK_VK_CHECK(func, ...) gsk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
-GskVulkanPipeline * gsk_vulkan_pipeline_new (GdkVulkanContext *context,
- VkRenderPass render_pass);
+GskVulkanPipelineLayout * gsk_vulkan_pipeline_layout_new (GdkVulkanContext *context);
+GskVulkanPipelineLayout * gsk_vulkan_pipeline_layout_ref (GskVulkanPipelineLayout *self);
+void gsk_vulkan_pipeline_layout_unref (GskVulkanPipelineLayout *self);
+
+VkPipelineLayout gsk_vulkan_pipeline_layout_get_pipeline_layout
+ (GskVulkanPipelineLayout *self);
+VkDescriptorSetLayout gsk_vulkan_pipeline_layout_get_descriptor_set_layout
+ (GskVulkanPipelineLayout *self);
+
+
+GskVulkanPipeline * gsk_vulkan_pipeline_new (GskVulkanPipelineLayout *layout,
+ const char *shader_name,
+ VkRenderPass render_pass);
-VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self);
-VkPipelineLayout gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self);
-VkDescriptorSetLayout gsk_vulkan_pipeline_get_descriptor_set_layout (GskVulkanPipeline *self);
+VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self);
G_END_DECLS
VkCommandPool command_pool;
VkFence fence;
VkRenderPass render_pass;
+ GskVulkanPipelineLayout *layout;
GHashTable *descriptor_set_indexes;
VkDescriptorPool descriptor_pool;
NULL,
&self->render_pass);
- self->pipeline = gsk_vulkan_pipeline_new (self->vulkan, self->render_pass);
+ self->layout = gsk_vulkan_pipeline_layout_new (self->vulkan);
+
+ self->pipeline = gsk_vulkan_pipeline_new (self->layout, "blit", self->render_pass);
return self;
}
VkDescriptorSetLayout layouts[needed_sets];
for (i = 0; i < needed_sets; i++)
{
- layouts[i] = gsk_vulkan_pipeline_get_descriptor_set_layout (self->pipeline);
+ layouts[i] = gsk_vulkan_pipeline_layout_get_descriptor_set_layout (self->layout);
}
GSK_VK_CHECK (vkAllocateDescriptorSets, device,
&(VkDescriptorSetAllocateInfo) {
for (l = self->render_passes; l; l = l->next)
{
- gsk_vulkan_render_pass_draw (l->data, self, self->pipeline, self->command_buffer);
+ gsk_vulkan_render_pass_draw (l->data, self, self->layout, self->command_buffer);
}
vkCmdEndRenderPass (self->command_buffer);
g_clear_object (&self->pipeline);
+ g_clear_pointer (&self->layout, gsk_vulkan_pipeline_layout_unref);
+
vkDestroyRenderPass (device,
self->render_pass,
NULL);